package com.bytedance.frameworks.baselib.network.dispatcher;

import com.bytedance.common.utility.b.ThreadPlus;

import java.util.concurrent.PriorityBlockingQueue;
import java.util.concurrent.atomic.AtomicInteger;

public class RequestQueue {
    private static AtomicInteger counter = new AtomicInteger();
    private volatile boolean isDispatcherInitialized;
    private static volatile RequestQueue instance;
    private final PriorityBlockingQueue<IRequest> apiLocalRequestQueue;
    private final PriorityBlockingQueue<IRequest> apiRequestQueue;
    private final PriorityBlockingQueue<IRequest> downloadRequestQueue;
    private ApiDispatcher[] apiDispatchers;
    private DownloadDispatcher[] downloadDispatchers;
    private ApiLocalDispatcher apiLocalDispatcher;

    private RequestQueue() {
        this.isDispatcherInitialized = false;
        this.apiLocalRequestQueue = new PriorityBlockingQueue();
        this.apiRequestQueue = new PriorityBlockingQueue();
        this.downloadRequestQueue = new PriorityBlockingQueue();
        this.apiDispatchers = new ApiDispatcher[4];
        this.downloadDispatchers = new DownloadDispatcher[4];
    }

    public static RequestQueue getInstance() {
        if (instance == null) {
            synchronized (RequestQueue.class) {
                if (instance == null) {
                    instance = new RequestQueue();
                }
            }
        }
        return instance;
    }

    public synchronized final void downloadRequestEnqueue(AbsRequest request) {
        if (request != null) {
            request.setSequence(counter.incrementAndGet());
            if (!this.isDispatcherInitialized) {
                this.ensureDispatchers();
            }

            if (request.getPriority() == IRequest.Priority.IMMEDIATE) {
                ThreadPlus.submitRunnable(request);
                return;
            }

            this.downloadRequestQueue.add(request);
        }
    }

    public synchronized final void apiRequestEnqueue(AbsRequest absRequest) {
        if (absRequest != null) {
            absRequest.setSequence(counter.incrementAndGet());
            if (!this.isDispatcherInitialized) {
                this.ensureDispatchers();
            }

            if (absRequest.needTryLocal()) {
                this.apiLocalRequestQueue.add(absRequest);
                return;
            }

            if (absRequest.getPriority() == IRequest.Priority.IMMEDIATE) {
                ThreadPlus.submitRunnable(absRequest);
                return;
            }
            this.apiRequestQueue.add(absRequest);
        }
    }

    private synchronized void ensureDispatchers() {
        int v0 = 0;
        this.releaseDispatchers();
        this.apiLocalDispatcher = new ApiLocalDispatcher(this.apiLocalRequestQueue, this.apiRequestQueue);
        this.apiLocalDispatcher.start();
        for (int i = 0; i < this.apiDispatchers.length; ++i) {
            ApiDispatcher v2 = new ApiDispatcher(this.apiRequestQueue, "ApiDispatcher-Thread", "ApiDispatcher");
            this.apiDispatchers[i] = v2;
            v2.start();
        }

        while (v0 < this.apiDispatchers.length) {
            DownloadDispatcher v1_1 = new DownloadDispatcher(this.downloadRequestQueue, "DownloadDispatcher-Thread", "DownloadDispatcher");
            this.downloadDispatchers[v0] = v1_1;
            v1_1.start();
            ++v0;
        }
        this.isDispatcherInitialized = true;
    }

    private synchronized void releaseDispatchers() {
        this.isDispatcherInitialized = false;
        if (this.apiLocalDispatcher != null) {
            this.apiLocalDispatcher.a = true;
            this.apiLocalDispatcher.interrupt();
        }

        for (int i = 0; i < this.apiDispatchers.length; ++i) {
            if (this.apiDispatchers[i] != null) {
                this.apiDispatchers[i].release();
                this.apiDispatchers[i] = null;
            }
        }

        int i = 0;
        while (true) {
            if (i >= this.downloadDispatchers.length) {
                return;
            }

            if (this.downloadDispatchers[i] != null) {
                this.downloadDispatchers[i].release();
                this.downloadDispatchers[i] = null;
            }
            ++i;
            continue;
        }
    }
}

